/**
 * 
 */
package com.google.code.cisx.store.jpa;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.openjpa.persistence.test.SingleEMTestCase;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.sessions.Session;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * Test Case support class that allows extensions to load test data from
 * specified SQL files.
 * <p>
 * This also implements Spring's {@link ApplicationContextAware} interface that
 * allows the {@link ApplicationContext} to be made available to this test
 * case's extensions.
 * 
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @since 1.0
 * @version $Id: ApplicationContextAwareStoreTestCase.java 4 2007-12-18
 *          19:18:54Z rahul.thakur.xdev $
 */
public abstract class StoreTestSupport extends SingleEMTestCase {

  /**
   * Commons Logging.
   */
  private static final Log log = LogFactory.getLog(StoreTestSupport.class);

  /**
   * Continuum Store persistent unit defined in <code>persistence.xml</code>
   * used by tests.
   */
  private static final String PERSISTENT_UNIT_CISX_STORE = "cisx-store";

  /**
   * @see org.apache.openjpa.persistence.test.SingleEMTestCase#setUp()
   */
  @Override
  public void setUp() {
    super.setUp();
  }

  /**
   * @see org.apache.openjpa.persistence.test.SingleEMTestCase#tearDown()
   */
  @Override
  public void tearDown() throws Exception {
    super.tearDown();
  }

  /**
   * Imports sql from the specified file.
   * 
   * @param sqlResource
   *          Resource containing sql
   */
  public void loadSqlSource(File sqlResource) {
    try {
      if (log.isDebugEnabled())
        log.debug("Loading sql: " + sqlResource.getAbsolutePath());
      List<String> statements = new ArrayList<String>(20);
      BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(sqlResource)));
      String line = null;
      StringBuffer currentStatement = new StringBuffer();
      while ((line = br.readLine()) != null) {
        if (line.trim().length() == 0)
          continue;
        if (line.trim().startsWith("#"))
          continue;

        currentStatement.append(line);
        if (line.endsWith(";")) {
          statements.add(currentStatement.toString());
          currentStatement = new StringBuffer();
        }
      }
      // append a line if missing a ';'
      if (currentStatement.length() > 0) {
        statements.add(currentStatement.toString());
      }
      runSQLStatements(statements);
    } catch (Throwable e) {
      if (log.isErrorEnabled())
        log.error("Problem executing SQL!", e);
    }
  }

  /**
   * Run a bunch of SQL statements.
   * 
   * @param statements
   *          Statements to run.
   * @throws SQLException
   */
  public void runSQLStatements(final List<String> statements) throws SQLException {
    if (statements.size() > 0 && log.isDebugEnabled())
      log.debug("Importing SQL statments:");
    
    for (String qry : statements) {
      org.eclipse.persistence.jpa.JpaEntityManager eclipseLinkEM = (org.eclipse.persistence.jpa.JpaEntityManager) this.em;
      Connection con = null;      
      // TODO: How to obtain JDBC Connection from underlying EntityManager?
      Session activeSession = eclipseLinkEM.getActiveSession();      
      con = (Connection) ((AbstractSession)activeSession).getAccessor().getConnection();
      try {
        Statement stmt = con.createStatement();

        // if (log.isDebugEnabled())
        // System.out.println(qry);

        stmt.execute(qry);
        con.commit();
      } catch (SQLException e) {
        try {
          con.rollback();
        } catch (SQLException e1) {
          if (log.isErrorEnabled())
            log.error("Unable to rollback transaction.");
          throw e1;
        }
        throw e;
      }
    }
    if (statements.size() > 0 && log.isDebugEnabled())
      log.debug("SQL import done!");
  }

  /**
   * Returns the name of the persistent-unit setup in
   * <code>persistence.xml</code>.
   */
  @Override
  protected String getPersistenceUnitName() {
    return PERSISTENT_UNIT_CISX_STORE;
  }

}
